package com.loby.monitor.excess.local;

import lombok.Builder;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * 单个污染因子监测数据超标条件
 * @author lobyliang
 * on 2020/1/4 10:57
 */
@Data
@Builder
public class DataExcessCondition implements Serializable
{

    /**
     * 报警规则ID，用于连接报警接收人
     * 排放口-污染因子超标判断规则ID
     */
    private long stationPollExcessRoleId;
    /**
     * 组份代码，污染因子代码（包括数值变量和开关量）
     */
    private String compositionCode;

    /**
     * 报警数据类型，AI还是DI
     */
    private InstrumentDataType dataType;

    /**
     * 是否发送超标信息
     */
    private boolean excessEnabled;

    /**
     * 是否发送超量程信息
     */
    private boolean overRangeEnabled;

    /**
     * 量程上限，null标识不检测
     */
    private Double rangeUpperLimit;
    /**
     * 量程下限，null标识不检测
     */
    private Double rangeLowerLimit;

    /**
     * 超标上限，null标识不检测
     */
    private Double upperThreshold;

    /**
     * 超标下限，null标识不检测
     */
    private Double lowerThreshold;

    /**
     * DI开关量报警数值，即等于这个值就报警
     */
    private Boolean diAlarmValue;

    /**
     * 实时数据-判断超标的模式
     */
    private ExcessMode realDataExcessMode;

    /**
     * 实时数据-判断报警消息的持续时间要求
     */
    private AlarmTimeMode realDataAlarmTimeMode;

    /**
     * 实时数据-报警间隔时间，单位秒(次数时为次数）
     * 发送一次报警后，下次报警必须等待的秒/次数
     * Null则不等待
     */
    private Integer realDataAlarmInterval;

    /**
     * 配合AlarmTimeMode = LastCount
     * 实时数据-报警持续的次数
     */
    @Builder.Default
    private int realAlarmLastCounter = 0;

    /**
     * 配合AlarmTimeMode = LastTime
     * 实时数据-报警持续的次数
     */
    private LocalDateTime realAlarmLastTimeBegin;
    /**
     * 最新一个监测数据
     */
    @Builder.Default
    private Double  realDataLastValue = null;

    /**
     * 实时数据-连续衡值报警的数量阀值
     */
    @Builder.Default
    private int realSameValueAlarmAmount= 0;

    /**
     * 实时数据-连续0值报警的数量阀值
     */
    @Builder.Default
    private int realZeroValueAlarmAmount = 0;

    /**
     * 实时数据-相同数据计数器（0值计数器暂时不考虑，用同一个）
     */
    @Builder.Default
    private int  realDataSameValueCounter=0;


    /**
     * 分钟数据-判断超标的模式
     */
    private ExcessMode minDataExcessMode;

    /**
     * 实时数据-判断报警消息的持续时间要求
     */
    private AlarmTimeMode minDataAlarmTimeMode;

    /**
     * 分钟数据-报警间隔时间，单位秒(次数时为次数）
     * 发送一次报警后，下次报警必须等待的秒/次数
     * Null则不等待
     */
    private Integer minDataAlarmInterval;

    /**
     * 配合AlarmTimeMode
     * 分钟数据-报警持续的时间或次数
     */
    @Builder.Default
    private int minAlarmLastCounter = 0;

    /**
     * 配合AlarmTimeMode = LastTime
     * 分钟数据-报警持续的次数
     */
    private LocalDateTime minAlarmLastTimeBegin;

    /**
     * 最新一个监测数据
     */
    @Builder.Default
    private Double  minDataLastValue = null;
    /**
     * 分钟数据-连续衡值报警的数量阀值
     */
    @Builder.Default
    private int minSameValueAlarmAmount = 0;

    /**
     * 分钟数据-连续0值报警的数量阀值
     */
    @Builder.Default
    private int minZeroValueAlarmAmount = 0;

    /**
     * 分钟数据-相同数据计数器（0值计数器暂时不考虑，用同一个）
     */
    @Builder.Default
    private int  minDataSameValueCounter=-1;

    /**
     * 小时数据-判断超标的模式
     */
    private ExcessMode hourDataExcessMode;

    /**
     * 小时数据-判断报警消息的持续时间要求
     */
    private AlarmTimeMode hourDataAlarmTimeMode;

    /**
     * 小时数据-报警间隔时间，单位秒(次数时为次数）
     * 发送一次报警后，下次报警必须等待的秒/次数
     * Null则不等待
     */
    private Integer hourDataAlarmInterval;

    /**
     * 配合AlarmTimeMode
     * 小时数据-报警持续的时间或次数
     */
    @Builder.Default
    private int hourAlarmLastCounter = 0;


    /**
     * 配合AlarmTimeMode = LastTime
     * 小时数据-报警持续的次数
     */
    private LocalDateTime hourAlarmLastTimeBegin;

    /**
     * 最新一个监测数据
     */
    @Builder.Default
    private Double  hourDataLastValue = null;

    /**
     * 小时数据-连续衡值报警的数量阀值
     */
    @Builder.Default
    private int hourSameValueAlarmAmount = 0;

    /**
     * 小时数据-连续0值报警的数量阀值
     */
    @Builder.Default
    private int hourZeroValueAlarmAmount = 0;

    /**
     * 小时数据-相同数据计数器（0值计数器暂时不考虑，用同一个）
     */
    @Builder.Default
    private int  hourDataSameValueCounter=-1;
    /**
     * 日数据-判断超标的模式
     */
    @Builder.Default
    private ExcessMode dayDataExcessMode=ExcessMode.None;

    /**
     * 日数据-判断报警消息的持续时间要求
     * 日数据仅支持立即报警和固定时间报警
     */
    private AlarmTimeMode dayDataAlarmTimeMode;


    /**
     * 固定时间报警
     * 固定在某一天的某个时间报警，小时：分钟这样，
     * null则有报警就发送
     */
    @Builder.Default
    private LocalTime realStaticTime = null;

    /**
     * 固定时间报警
     * 固定在某一天的某个时间报警，小时：分钟这样，
     * null则有报警就发送
     */
    @Builder.Default
    private LocalTime minStaticTime = null;

    /**
     * 固定时间报警
     * 固定在某一天的某个时间报警，小时：分钟这样，
     * null则有报警就发送
     */
    @Builder.Default
    private LocalTime hourStaticTime = null;

    /**
     * 固定时间报警
     * 固定在某一天的某个时间报警，小时：分钟这样，
     * null则有报警就发送
     */
    @Builder.Default
    private LocalTime dayStaticTime = null;
    /**
     * 判断，计算一天开始和结束的时间
     * 默认为 0点0分开始算一天，过0点清理缓存
     * 大气会是12：00分开始算一天
     */
    @Builder.Default
    private LocalTime startTime = LocalTime.of(0,0);

    /**
     * 上次计时的时间
     */
    @Builder.Default
    private LocalDateTime runtimeLastStartTime = null;

    /**
     * +1，并判断是否报警
     * @param dataType 数据来源类型
     * @return 是否超过了报警数量阀值
     */
    public boolean increaseDataZeroValueCounter(AlarmDataType dataType)
    {
        switch (dataType)
        {
            case RealData:return increaseRealDataZeroValueCounter();
            case ContMinData:return increaseMinDataZeroValueCounter();
            case ContHourData:return increaseHourDataZeroValueCounter();
            case ContDayData:
            default:return false;
        }
    }

    /**
     * +1，并判断是否报警
     * @param dataType 数据来源类型
     * @return 是否超过了报警数量阀值
     */
    public boolean increaseDataConstantValueCounter(AlarmDataType dataType)
    {
        switch (dataType)
        {
            case RealData:return increaseRealDataSameValueCounter();
            case ContMinData:return increaseMinDataSameValueCounter();
            case ContHourData:return increaseHourDataSameValueCounter();
            case ContDayData:
            default:return false;
        }
    }

    public boolean increaseRealDataZeroValueCounter() {
        if(realZeroValueAlarmAmount>0)
        {
            realDataSameValueCounter +=1;
            return realDataSameValueCounter >= realZeroValueAlarmAmount;
        }
        return false;
    }


    public boolean increaseRealDataSameValueCounter() {
        if(realSameValueAlarmAmount>0)
        {
            realDataSameValueCounter +=1;
            return realDataSameValueCounter >= realSameValueAlarmAmount;
        }
        return false;
    }

    public boolean increaseMinDataZeroValueCounter() {
        if(minZeroValueAlarmAmount>0)
        {
            minDataSameValueCounter +=1;
            return minDataSameValueCounter >= minZeroValueAlarmAmount;
        }
        return false;
    }


    public boolean increaseMinDataSameValueCounter() {
        if(minSameValueAlarmAmount>0)
        {
            minDataSameValueCounter +=1;
            return minDataSameValueCounter >= minSameValueAlarmAmount;
        }
        return false;
    }

    public boolean increaseHourDataZeroValueCounter() {
        if(hourZeroValueAlarmAmount>0)
        {
            hourDataSameValueCounter +=1;
            return hourDataSameValueCounter >= hourZeroValueAlarmAmount;
        }
        return false;
    }


    public boolean increaseHourDataSameValueCounter() {
        if(hourSameValueAlarmAmount>0)
        {
            hourDataSameValueCounter +=1;
            return hourDataSameValueCounter >= hourSameValueAlarmAmount;
        }
        return false;
    }

    public void setDataSameValueCounter(int i, AlarmDataType dataType) {
        switch (dataType)
        {
            case RealData:realDataSameValueCounter = i;
                break;
            case ContMinData:minDataSameValueCounter = i;
                break;
            case ContHourData:hourDataSameValueCounter = i;
                break;
            case ContDayData:
            default:break;
        }
    }

    public void setDataLastValue(Double value, AlarmDataType dataType) {
        switch (dataType)
        {
            case RealData:realDataLastValue = value;
                break;
            case ContMinData:minDataLastValue = value;
                break;
            case ContHourData:hourDataLastValue = value;
                break;
            case ContDayData:
            default:break;
        }
    }

    public boolean isEqualLastValue(Double value, AlarmDataType dataType) {
        switch (dataType)
        {
            case RealData:return realDataLastValue != null && realDataLastValue.equals(value);
            case ContMinData:return minDataLastValue != null && minDataLastValue.equals(value);
            case ContHourData:return hourDataLastValue != null && hourDataLastValue.equals(value);
            case ContDayData:
            default:break;
        }
        return false;
    }

    /**
     * 计数器+1
     * 判断超标报警时候达到阈值规定次数
     * @return 是否报警
     */
    public boolean isRealDataLastCountAlarm() {
        realAlarmLastCounter += 1;
        return realDataAlarmInterval!= null && realDataAlarmInterval != 0 && realAlarmLastCounter >= realDataAlarmInterval;
    }

    /**、
     * 计数器+1
     * 判断超标报警时候达到阈值规定次数
     * @return 是否报警
     */
    public boolean isMinDataLastCountAlarm() {
        minAlarmLastCounter += 1;
        return minDataAlarmInterval!= null && minDataAlarmInterval != 0 && minAlarmLastCounter >= minDataAlarmInterval;
    }

    /**
     * 计数器+1
     * 判断超标报警时候达到阈值规定次数
     * @return 是否报警
     */
    public boolean isHourDataLastCountAlarm() {
        hourAlarmLastCounter += 1;
        return hourDataAlarmInterval!= null && hourDataAlarmInterval != 0 && hourAlarmLastCounter >= hourDataAlarmInterval;
    }

    public DataExcessCondition(long stationPollExcessRoleId, String compositionCode, InstrumentDataType dataType, boolean excessEnabled, boolean overRangeEnabled, Double rangeUpperLimit, Double rangeLowerLimit, Double upperThreshold, Double lowerThreshold, Boolean diAlarmValue, ExcessMode realDataExcessMode, AlarmTimeMode realDataAlarmTimeMode, Integer realDataAlarmInterval, int realAlarmLastCounter, LocalDateTime realAlarmLastTimeBegin, Double realDataLastValue, int realSameValueAlarmAmount, int realZeroValueAlarmAmount, int realDataSameValueCounter, ExcessMode minDataExcessMode, AlarmTimeMode minDataAlarmTimeMode, Integer minDataAlarmInterval, int minAlarmLastCounter, LocalDateTime minAlarmLastTimeBegin, Double minDataLastValue, int minSameValueAlarmAmount, int minZeroValueAlarmAmount, int minDataSameValueCounter, ExcessMode hourDataExcessMode, AlarmTimeMode hourDataAlarmTimeMode, Integer hourDataAlarmInterval, int hourAlarmLastCounter, LocalDateTime hourAlarmLastTimeBegin, Double hourDataLastValue, int hourSameValueAlarmAmount, int hourZeroValueAlarmAmount, int hourDataSameValueCounter, ExcessMode dayDataExcessMode, AlarmTimeMode dayDataAlarmTimeMode, LocalTime realStaticTime, LocalTime minStaticTime, LocalTime hourStaticTime, LocalTime dayStaticTime, LocalTime startTime, LocalDateTime runtimeLastStartTime) {
        this.stationPollExcessRoleId = stationPollExcessRoleId;
        this.compositionCode = compositionCode;
        this.dataType = dataType;
        this.excessEnabled = excessEnabled;
        this.overRangeEnabled = overRangeEnabled;
        this.rangeUpperLimit = rangeUpperLimit;
        this.rangeLowerLimit = rangeLowerLimit;
        this.upperThreshold = upperThreshold;
        this.lowerThreshold = lowerThreshold;
        this.diAlarmValue = diAlarmValue;
        this.realDataExcessMode = realDataExcessMode;
        this.realDataAlarmTimeMode = realDataAlarmTimeMode;
        this.realDataAlarmInterval = realDataAlarmInterval;
        this.realAlarmLastCounter = realAlarmLastCounter;
        this.realDataExcessMode = realDataExcessMode;
        this.realDataAlarmTimeMode = realDataAlarmTimeMode;
        this.realDataAlarmInterval = realDataAlarmInterval;
        this.realAlarmLastCounter = realAlarmLastCounter;
        this.realAlarmLastTimeBegin = realAlarmLastTimeBegin;
        this.realDataLastValue = realDataLastValue;
        this.realSameValueAlarmAmount = realSameValueAlarmAmount;
        this.realZeroValueAlarmAmount = realZeroValueAlarmAmount;
        this.realDataSameValueCounter = realDataSameValueCounter;
        this.minDataExcessMode = minDataExcessMode;
        this.minDataAlarmTimeMode = minDataAlarmTimeMode;
        this.minDataAlarmInterval = minDataAlarmInterval;
        this.minAlarmLastCounter = minAlarmLastCounter;
        this.minAlarmLastTimeBegin = minAlarmLastTimeBegin;
        this.minDataLastValue = minDataLastValue;
        this.minSameValueAlarmAmount = minSameValueAlarmAmount;
        this.minZeroValueAlarmAmount = minZeroValueAlarmAmount;
        this.minDataSameValueCounter = minDataSameValueCounter;
        this.hourDataExcessMode = hourDataExcessMode;
        this.hourDataAlarmTimeMode = hourDataAlarmTimeMode;
        this.hourDataAlarmInterval = hourDataAlarmInterval;
        this.hourAlarmLastCounter = hourAlarmLastCounter;
        this.hourAlarmLastTimeBegin = hourAlarmLastTimeBegin;
        this.hourDataLastValue = hourDataLastValue;
        this.hourSameValueAlarmAmount = hourSameValueAlarmAmount;
        this.hourZeroValueAlarmAmount = hourZeroValueAlarmAmount;
        this.hourDataSameValueCounter = hourDataSameValueCounter;
        this.dayDataExcessMode = dayDataExcessMode;
        this.dayDataAlarmTimeMode = dayDataAlarmTimeMode;
        this.realStaticTime = realStaticTime;
        this.minStaticTime = minStaticTime;
        this.hourStaticTime = hourStaticTime;
        this.dayStaticTime = dayStaticTime;
        this.startTime = startTime;
        this.runtimeLastStartTime = runtimeLastStartTime;
    }
}
